package com.bangdao.lock;

/**
 * @author chen
 * @create 2021-01-06
 */

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁
 * **读写锁允许同一时刻被多个读线程访问，但是在写线程访问时，所有的读线程和其他的写线程都会被阻塞**。
 */
public class ReentrantReadWriteLockDemo {
    public static void main(String[] args) {
        MyCache myCache = new MyCache();
        for (int i = 1; i <= 5; i++) {
            String num = String.valueOf(i);
            // 开启5个写线程
            new Thread(() -> {
                myCache.put(num, num);
            }, num).start();
        }
        for (int i = 1; i <= 5; i++) {
            String num = String.valueOf(i);
            // 开启5个读线程
            new Thread(() -> {
                myCache.get(num);
            }, num).start();
        }
    }
}

class MyCache {
    /**
     * volatile:可见性、禁制令重排、不具备原子性
     */
    private volatile Map<String, String> map = new HashMap<>();
    // 加入读写锁
    ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

    //写入方法
    public void put(String key, String value) {
        // 加写锁
        rwl.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "开始写入。。。。");
            Thread.sleep(300);
            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + "写入完成。。。。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 释放写锁
            rwl.writeLock().unlock();
        }
    }

    //读取方法
    public void get(String key) {
        //加读锁
        rwl.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "开始读取。。。");
            Thread.sleep(300);
            String value = map.get("key");
            System.out.println(Thread.currentThread().getName() + "读取完成。。。" + value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //释放锁
            rwl.readLock().unlock();
        }
    }
}